import sys
import os
from . import builders
from .logging import loginfo, logstat
from .core import Node, Namespace, mark_unchanged
from .cliopts import CliOpts, switch
from .defaults import params as default_params
from .common import common_namespace
from . import task



def load_builders():
    for name, mod in builders.__dict__.iteritems():
        if hasattr(mod, "register_builder"):
            mod.register_builder()


def build(nodelist, force = False):
    if not force:
        if mark_unchanged(nodelist) == 0:
            logstat("BUILD", "project is up to date")
            return
    logstat("BUILD", "building begins")
    for node in nodelist:
        node.build()
    task.wait_all()
    root = nodelist[-1]
    if root.success:
        logstat("BUILD", "build SUCCEEDED")
    else:
        logstat("BUILD", "build FAILED")
    return root.success


def cleanup(nodelist):
    logstat("CLEAN", "cleaning begins")
    for node in nodelist:
        node.clean()
    logstat("CLEAN", "project tree has been cleaned")
    return True


class GabotMain(CliOpts):
    """Gabot Build System"""
    
    # CliOpts params
    program_name = "gabot"
    program_version = "1.00"
    min_tail_args = 1
    max_tail_args = 1
    usage = "[OPTIONS] projectfile"
    
    # consts
    MODE_BUILD = 1
    MODE_FORCE_BUILD = 2
    MODE_CLEAN = 3
    modesmap = {
        'build' : MODE_BUILD, 
        'force' : MODE_FORCE_BUILD,
        'clean' : MODE_CLEAN,
    }
    
    # defaults
    default_configfile = "config.gabot"
    configfile = None
    load_default_configfile = True
    mode = MODE_BUILD
    
    @switch("c", "config", args=[str])
    def sw_config(self, filename):
        """loads given configuration file"""
        self.configfile = filename
    
    @switch(long_name = "noconfig", args=[])
    def sw_noconfig(self):
        """disables loading the default config file"""
        self.load_default_configfile = False
    
    @switch("m", "mode", args=[str])
    def sw_mode(self, mode):
        """selects operation mode: 
        'build' - rebuild only changed files; 
        'force' - rebuild all files (even unchanged); 
        'clean' - delete all previous build products and cache"""
        if mode in self.modesmap:
            self.mode = self.modesmap[mode]
        else:
            raise ValueError("invalid mode: %r" % (mode,))
    
    def main(self, projfile):
        if (self.configfile is None and self.load_default_configfile and 
        os.path.exists(self.default_configfile)):
            self.configfile = self.default_configfile
        if self.configfile is not None:
            loginfo("MAIN", "loading config file %r", self.configfile)
            execfile(self.configfile, common_namespace.copy())
        
        load_builders()
        rootnode = Node.create(projfile)
        rootnode.params = default_params
        rootnode.scan_all()
        nodelist = rootnode.toposort()
        
        if self.mode == self.MODE_BUILD:
            loginfo("MAIN", "mode: rebuild changed project files")
            ret = build(nodelist)
        elif self.mode == self.MODE_FORCE_BUILD:
            loginfo("MAIN", "mode: rebuild entire project")
            ret = build(nodelist, force = True)
        elif self.mode == self.MODE_CLEAN:
            loginfo("MAIN", "mode: clean project tree")
            ret = cleanup(nodelist)
        else:
            raise ValueError("invalid mode: %r" % (self.mode,))
        
        return ret
    


main = GabotMain()















